<template>
	<view v-if="show" :class="{popup: popup}">
		<view v-if="popup" class="popup-mask" @click="clickMask"></view>
		<view :style="[boxStyle]">
			<view v-if="type === 'hollowDots'" class="hollow-dots-spinner">
				<view class="dot"></view>
				<view class="dot"></view>
				<view class="dot"></view>
			</view>
			<view v-else-if="type === 'halfCircle'" class="half-circle-spinner">
				<view class="circle circle-1"></view>
				<view class="circle circle-2"></view>
			</view>
			<view v-else-if="type === 'rotateCircle'" class="rotate-circle-spinner">
				<view class="circle"></view>
			</view>
			<view v-else-if="type === 'chrysanthemum'" class="chrysanthemum-spinner">
				<view class="half-spin" v-for="i in 2" :key="i">
					<text class="spin-item"></text>
					<text class="spin-item"></text>
					<text class="spin-item"></text>
					<text class="spin-item"></text>
				</view>
			</view>
			<view v-else-if="type === 'swappingSquares'" class="swapping-squares-spinner">
				<view class="square"></view>
				<view class="square"></view>
				<view class="square"></view>
				<view class="square"></view>
			</view>
			<view v-else-if="type === 'custom'" class="custom-spinner" :class="{'custom-rotate': imageRotate}">
				<image class="img" :src="loadingImage" :style="{width: size*1.5 + 'px', height: size*1.5 + 'px'}" mode="widthFix"></image>
			</view>
		</view>
		<view class="info">加载中...</view>
	</view>
</template>

<script setup>
	import { ref, watch, computed } from 'vue'
	const emits = defineEmits(['update:modelValue'])
	
	const props = defineProps({
		// 是否可见，父组件中来触发是否显示
		modelValue: {
			type: Boolean,
			default: undefined
		},
		// 加载动画，可选类型参数(hollowDots, halfCircle, rotateCircle, chrysanthemum, swappingSquares)
		type: {
			type: String,
			default: 'halfCircle'
		},
		// 加载类型使用自定义custom时，使用loading的图片gif
		loadingImage: {
			type: String,
			default: ''
		},
		// 图片旋转
		imageRotate: {
			type: Boolean,
			default: false
		},
		// 动画元素颜色
		color: {
			type: String,
			default: '#888888'
		},
		size: {
			type: Number,
			default: 30
		},
		// 是否弹窗蒙版加载
		popup: {
			type: Boolean,
			default: false
		},
		// 是否可点击蒙版关闭
		maskClick: {
			type: Boolean,
			default: false
		}
	})
	let boxStyle = computed(()=>{
		if(props.type == 'hollowDots'){
			return {
				'width': uni.$xl.calcUnit(props.size * 3 + props.size * 3 / 5),
				'height': uni.$xl.calcUnit(props.size / 2 + props.size / 5),
				'--color': props.color,
				'--size': uni.$xl.calcUnit(props.size)
			};
		}else if(props.type == 'swappingSquares'){
			return {
				'width': uni.$xl.calcUnit(props.size * 5 / 4),
				'height':  uni.$xl.calcUnit(props.size * 5 / 4),
				'--color': props.color,
				'--size': uni.$xl.calcUnit(props.size)
			};
		}else if(props.type == 'custom'){
			return {
				'width': uni.$xl.calcUnit(props.size * 3),
				'height':  'auto'
			};
		}else{
			return {
				width: uni.$xl.calcUnit(props.size * 6 / 5),
				height:  uni.$xl.calcUnit(props.size * 6 / 5),
				'--color': props.color,
				'--size': uni.$xl.calcUnit(props.size)
			};
		}
	})
	
	let show = ref(true)
	watch( () => props.modelValue, (newValue, oldValue) => {
		if (newValue === undefined) show.value = true;
		else show.value = newValue
	}, { immediate: true })
	
	function clickMask(){
		if(props.maskClick){
			emits('update:modelValue', !show.value);
		}
	}
</script>

<style lang="scss" scoped>
	.popup{
		z-index: 99999;
		position: fixed;
		top: 0;
		bottom: 0;
		left: 0;
		right: 0;
		display: flex;
		justify-content: center;
		align-items: center;
		flex-direction: column;
		.info{
			display: flex;
			justify-content: center;
			align-items: center;
			margin-top: 20rpx;
			height: 100rpx;
			font-size: 38rpx;
			color: v-bind(color);
			position: relative;
			z-index: 1;
		}
	}
	.popup-mask {
		height: 100%;
		width: 100%;
		background-color: rgba(0, 0, 0, 0.4);
		position: absolute;
		top: 0;
		bottom: 0;
		left: 0;
		right: 0;
	}
	.info{
		display: none;
	}
	
	/* HollowDots  */
	.hollow-dots-spinner .dot {
	  width: calc(var(--size) / 2);
	  height: calc(var(--size) / 2);
	  margin: 0 calc(var(--size) / 4);
	  border: calc(var(--size) / 10) solid var(--color);
	  border-radius: 50%;
	  float: left;
	  transform: scale(0);
	  animation: hollowDots 1000ms ease infinite 0ms;
	}
	.hollow-dots-spinner .dot:nth-child(1) {
	  animation-delay: calc(300ms * 1);
	}
	.hollow-dots-spinner .dot:nth-child(2) {
	  animation-delay: calc(300ms * 2);
	}
	.hollow-dots-spinner .dot:nth-child(3) {
	  animation-delay: calc(300ms * 3);
	}
	@keyframes hollowDots {
	  50% {
		transform: scale(1);
		opacity: 1;
	  }
	  100% {
		opacity: 0;
	  }
	}
	
	/* halfCircle  */
	.half-circle-spinner .circle {
	  content: "";
	  position: absolute;
	  width: var(--size);
	  height: var(--size);
	  border-radius: 100%;
	  border: calc(var(--size) / 10) solid transparent;
	}
	
	.half-circle-spinner .circle.circle-1 {
	  border-top-color: var(--color);
	  animation: loading-rotate 1s infinite;
	}
	.half-circle-spinner .circle.circle-2 {
	  border-bottom-color: var(--color);
	  animation: loading-rotate 1s infinite alternate;
	}
	@keyframes loading-rotate {
		0% {
			transform: rotate(0);
		}
		100% {
			transform: rotate(360deg);
		}
	}
	
	
	/* rotateCircle */
	.rotate-circle-spinner .circle{
		width: var(--size);
		height: var(--size);
		border-radius: 100%;
		border-style: solid;
		border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) currentcolor;
		// border-width: calc(var(--size) / 10);
		border-width: 2px;
		animation: loading-rotate 1s linear infinite;
		color: var(--color);
	}
	
	/* chrysanthemum */
	.chrysanthemum-spinner{
		position: relative;
		// 注意+不能跟#连在一起
		width: calc(var(--size) + var(--size) / 5);
		height: calc(var(--size) + var(--size) / 5);
		animation: loading-rotate 2s linear infinite;
		.half-spin {
			position: absolute;
			left: 0;
			top: 0;
			height: 100%;
			width: 100%;
			.spin-item {
				height: calc(var(--size) / 4);
				width: calc(var(--size) / 10);
				background-color: currentColor;
				position: absolute;
				border-radius: 5px;
				color: var(--color);
				&:nth-child(1){
					top: 0;
					left: calc(50% - var(--size) / 20);
				}
				&:nth-child(2){
					top: calc(50% - var(--size) / 8);
					right: calc(var(--size) / 8 - var(--size) / 20);
					transform: rotate(90deg);
				}
				&:nth-child(3){
					left: calc(50% - var(--size) / 20);
					bottom: 0;
				}
				&:nth-child(4){
					left: calc(var(--size) / 8 - var(--size) / 20);
					top: calc(50% - var(--size) / 8);
					transform: rotate(90deg)
				}
			}
			
			&:nth-child(2) {
				transform: rotate(45deg);
			}
		}
	}
	
	
	/* swappingSquares */
	.swapping-squares-spinner {
	  position: relative;
	  width: calc(var(--size) * 5 / 4);
	  height: calc(var(--size) * 5 / 4);
	}
	.swapping-squares-spinner .square {
	  height: calc(var(--size) * 0.25 / 1.3);
	  width:  calc(var(--size) * 0.25 / 1.3);
	  animation-duration: 1000ms;
	  border: calc(var(--size) * 0.04 / 1.3) solid var(--color);
	  margin-right: auto;
	  margin-left: auto;
	  position: absolute;
	  top: calc(var(--size) / 2);
	  left: calc(var(--size) / 2);
	  animation-iteration-count: infinite;
	}
	.swapping-squares-spinner .square:nth-child(1) {
	  animation-name: swappingSquares-child-1;
	  animation-delay: 500ms;
	}
	.swapping-squares-spinner .square:nth-child(2) {
	  animation-name: swappingSquares-child-2;
	  animation-delay: 0ms;
	}
	.swapping-squares-spinner .square:nth-child(3) {
	  animation-name: swappingSquares-child-3;
	  animation-delay: 500ms;
	}
	.swapping-squares-spinner .square:nth-child(4) {
	  animation-name: swappingSquares-child-4;
	  animation-delay: 0ms;
	}
	@keyframes swappingSquares-child-1 {
	  50% {
		transform: translate(150%,150%) scale(2,2);
	  }
	}
	@keyframes swappingSquares-child-2 {
	  50% {
		transform: translate(-150%,150%) scale(2,2);
	  }
	}
	@keyframes swappingSquares-child-3 {
	  50% {
		transform: translate(-150%,-150%) scale(2,2);
	  }
	}
	@keyframes swappingSquares-child-4 {
	  50% {
		transform: translate(150%,-150%) scale(2,2);
	  }
	}
	
	.custom-rotate .img{
		animation: loading-rotate 1s linear infinite;
	}
</style>
